#include "approxy4esp.h"
#include "protocol.h"
#include "cJSON.h"
#include "im4c.h"
#include "md5.h"
#include "esp_log.h"
#include "hex.h"
#include "aes.h"


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "socket_wrapper.h"

#define VERSION_03X

//#define _BEAT_DBUG
//#undef  _BEAT_DBUG
#define PRINT_USERNAME
#define BUF_SIZE 4096
#define THREAD_MODEL_NEW 1
#define THREAD_MODEL_POL 2
#define WATCHDOG_INIT  5;
#define WATCHDOG_TICKS  10 * 1000;
#define USER_RUNNING_STA_N 0
#define USER_RUNNING_STA_Y 1
#define LUT_CONNECTED 1
#define LUT_DISCONNECTED 0
#define WM_THREADMSG  WMUSER+100
#define MAX_LOOP_RECV_BUF 2048 //64KB
#define _SUPPORT_MAX_CLIENT 8


#define STOP			0		//线程停止
#define RUNING			1		//线程运行

#define DIGHOLE_FINE	1		//洞口正常
#define DIGHOLE_OLD		0		//洞口老化

#define SCAN_END		4		//扫描结束
#define SCAN_TIMEOUT	3		//扫描超时
#define SCAN_HANDLE		2		//扫描到结果
#define SCAN_WAITING	1		//等待扫描
#define SCAN_WAITNONE	0		//未进入扫描状态


#define RYN_HBSEKEYLEN				37
#define RYN_USE_THREADPOOL1
#define RYN_WorkThreadWatchDogMin	0
#define RYN_WorkThreadWatchDogMax	15
#define RYN_LOGIN_STA_NONE			0		// # 未登录状态
#define RYN_LOGIN_STA_RUNNING		1		// # 正在运行状态
#define RYN_LOGIN_STA_SUCC			2		// # 登陆成功状态
#define RYN_LOGIN_STA_FAIL			3		// # 登陆失败状态
#define RYN_LOGIN_STA_DENY			4		// # 禁用状态
#define RYN_LOGIN_STA_NOTACTIVE		5		// # 未激活状态
#define RYN_LOGIN_STA_TIMEOUT		6		// # 登录超时
#define RYN_LOGIN_TIMEOUT			3000	// # 超时时间 3秒
#define RYN_DEFAULT_ROUTEPORT		50033	//

#define TAG "approxy"

// ApproxyCfgST_t * approxy_cfg_st		= NULL; // Approxy配置属性
Approxy4cST_t	*approxy4cST_t_s[_SUPPORT_MAX_CLIENT] = {0};//终端连接数据
int approxy4cST_t_count = 0;
void approxy4esp_task(void * parm);
void *LutServiceLoop(Approxy4cST_t *approxy4cST);
int approxy4c_needExit = 0;
/**AES加密变量 v0.3.x 版本使用*/
unsigned char IV_03X[16]		= Config_Aes_IV_03;

// char *clusterServerHostAndPort = "192.168.31.48:50033";
char *clusterServerHostAndPort = "192.168.31.218:50033";

// 初始化Approxy4cST
Approxy4cST_t *init_Approxy4cST(Approxy4cST_t *approxy4cST){
	approxy4cST = (Approxy4cST_t *)malloc(sizeof(Approxy4cST_t));
	memset(approxy4cST->gl_uidSTR,0,sizeof(approxy4cST->gl_uidSTR));
	memset(approxy4cST->gl_sidSTR,0,sizeof(approxy4cST->gl_sidSTR));
	memset(approxy4cST->glLoopServiceAddr,0,sizeof(approxy4cST->glLoopServiceAddr));
	memset(approxy4cST->pGlHbSeKey,0,sizeof(approxy4cST->pGlHbSeKey));

	approxy4cST->pGlHbPkg						= NULL;
	approxy4cST->nGlHbPkgLen					= 0;

	approxy4cST->nServerSTArraySize				= 0;
	approxy4cST->pGlUserName					= NULL;
	approxy4cST->nGlUserNameLen					= 0;
	approxy4cST->pGlPaasword					= NULL;
	approxy4cST->nGlPaaswordLen					= 0;
	approxy4cST->pGlSvrHost						= NULL;
	approxy4cST->nGlSvrHostLen					= 0;
	approxy4cST->nGlSvrPort						= 0;


	approxy4cST->nUserRunningSta				= USER_RUNNING_STA_Y;

	approxy4cST->nGlConnected					= LUT_DISCONNECTED;
	approxy4cST->pGlCoreDataAddrHost			= NULL;
	approxy4cST->nGlCoreDataAddrHostLen			= 0;
	approxy4cST->nGlCoreDataAddrPort			= 0;
	approxy4cST->nScanWaitSta					= SCAN_WAITNONE;
	approxy4cST->pGlP2PServerAddrHost			= NULL;
	approxy4cST->nGlP2PServerAddrHostLen		= 0;
	approxy4cST->nGlP2PServerAddrPort			= 0;
	approxy4cST->nGlSvrSockfd					= -1;
	approxy4cST->stayRun						= 0;
	approxy4cST->nUserLoginStatus				= RYN_LOGIN_STA_NONE;
	approxy4cST->channelID						= CHANNEL_BEGIN;
	return approxy4cST;
}

void destory_Approxy4cST(Approxy4cST_t *approxy4cST){
	int i = 0;
	if(approxy4cST){
		FreeBuf(approxy4cST->pGlHbPkg);
		FreeBuf(approxy4cST->pGlUserName);
		FreeBuf(approxy4cST->pGlPaasword);
		FreeBuf(approxy4cST->pGlSvrHost);
		FreeBuf(approxy4cST->pGlCoreDataAddrHost);
		FreeBuf(approxy4cST->pGlP2PServerAddrHost);
		for(i=0;i<approxy4cST->nServerSTArraySize;i++){
			FreeMem(approxy4cST->pServerSTArray[i]);
		}
	}
	FreeMem(approxy4cST);
}

Approxy4cST_t *FindApproxy4cSTByChannelID(int channelID){
	int i = 0;
	//fn_RYN_LOG_ERROR("channelID: %d",channelID);
	// if(!approxy4cST_t_s) return NULL;
	for(i=0;i<approxy4cST_t_count;i++){
		if(!approxy4cST_t_s[i]) return NULL;
		if(approxy4cST_t_s[i]->channelID == channelID){
			return approxy4cST_t_s[i];
		}
	}
	return NULL;
}

/************************************************************************/
/* 启动Approxy消息机制                                                    */
/************************************************************************/
esp_err_t start_Approxy4Esp(char *pUserName,int nUserNameLen,char *pPassword,int nPasswordLen,int nAutoLogin){
	int nRet = 0;
	Approxy4cST_t *approxy4cST = NULL;
	approxy4cST = init_Approxy4cST(approxy4cST);
	MallocBuf(char,approxy4cST->pGlUserName,nUserNameLen+1);
	MallocBuf(char,approxy4cST->pGlPaasword,nPasswordLen+1);
	memcpy_s(approxy4cST->pGlUserName,nUserNameLen,pUserName,nUserNameLen);
	memcpy_s(approxy4cST->pGlPaasword,nPasswordLen,pPassword,nPasswordLen);
	approxy4cST->nGlUserNameLen = nUserNameLen;
	approxy4cST->nGlPaaswordLen = nPasswordLen;

#ifdef PRINT_USERNAME
	fn_RYN_LOG_DEBUG(TAG,"UserName = %s",approxy4cST->pGlUserName);
#endif // PRINT_USERNAME

	approxy4cST->nUserLoginStatus = RYN_LOGIN_STA_NONE;

    if(approxy4cST->nServerSTArraySize == 0){
		//fn_RYN_LOG_DEBUG("没有从approxy_ua中获取到用户[%s]到主机地址和端口",approxy4cST->pGlUserName);
		GetClusterServer(approxy4cST);
	}

    // memset(approxy4cST->pServerSTArray[0]->serverIP,0,sizeof(approxy4cST->pServerSTArray[0]->serverIP));
    // memcpy(approxy4cST->pServerSTArray[0]->serverIP,mesServerHost,strlen(mesServerHost));
    // approxy4cST->pServerSTArray[0]->serverPort = mesServerPort;

    xTaskCreate(approxy4esp_task, "approxy4esp_task", 5120,  (void *)approxy4cST, 3, NULL);
    //approxy4esp_task(approxy4cST);
	return nRet;
}


/************************************************************************/
/* 运行线程入口                                                           */
/************************************************************************/
void approxy4esp_task(void * arg){
	Approxy4cST_t *approxy4cST = (Approxy4cST_t *)(arg);
	approxy4cST->nGlHbPkgLen = 0;

#ifdef VERSION_03X
	// v0.3.x -- start --
	fn_RYN_LOG_INFO(TAG,"VERSION_03X ..");
	if(1){
		LutServiceLoop(approxy4cST);
	}
	// v0.3.x -- end --
#endif
	
	fn_RYN_LOG_INFO(TAG,"End pthread_detach approxy4esp_task!!...");
}


/** 解析从服务器发送回来的sac数据包 **/
int HandleSacPackage(int * nSac,char * szRtJson, int * nRtJsonLen,int sockfd){
	int nRet = -1;
	int nReadSta = 0;
	int nRead = 0;
	const int debug = 0;
	nReadSta = fn_ReadTimeout(sockfd,SHB_READ_TIME);
	//fn_RYN_LOG_DEBUG(TAG,"fn_ReadTimeout nReadSta = %d",nReadSta);
	// 正常通信
	if(nReadSta == 0){
		char version;
		ProtocolHead_t *_protocolHead = NULL;
		char *_ReadBuf = NULL;
		int _protocolLen = 0;
		Bit16 cksum = 0;
		unsigned char _aesKey[16] = {0};
		unsigned char _signature[16] = {0};
		unsigned char * _encrypData = NULL;
		int _encrypDataLen = 0;
		unsigned char * _bodyData = NULL;
		int  _bodyDataLen = 0;
		char * _pureData = NULL;
		int _pureDataLen = 0;
		MD5Context_t md5ctx;
		unsigned char digest[16] = {0};
		Bit16 _bit16 = 0;
		char _tt[2] = {0};

		cJSON * pRoot = NULL;
		int errCode = 0;
		int nTotalBodyRead = 0;

		// 读取第一个字节，获取协议头长度
		nRead = fn_ReadPkg(sockfd,&version,1);
		//fn_RYN_LOG_DEBUG(TAG,"nRead = %d, %s, %02X",nRead,"读取第一个字节，获取协议头长度",version);
		// 网络异常或延时导致读取数据 < 0
		if (nRead < 0) {
			if (errno == EINTR)
				goto __END_HANDLE;
			if(debug){
				fn_RYN_LOG_DEBUG(TAG,"%d read() error, errno = %d, error = %s,%s", getpid(), errno,strerror(errno),"获取协议头长度");
			}
			goto __END_HANDLE;
			// 连接关闭
		}else if (nRead == 0) { // remote close
			fn_RYN_LOG_DEBUG(TAG,"Remote sockfd(%d) Close! %s",sockfd,"获取协议头长度");
			nRet = ERRCODE_SCKCLOSE;
			goto __END_HANDLE;
		}

		// 计算协议长度
		_protocolLen = (version >> 0x04 ) * (version & 0x0F);
		// 读取剩余协议头
		MallocMem(ProtocolHead_t,_protocolHead);
		_protocolHead->version = version;
		MallocBuf(char,_ReadBuf,_protocolLen);
		memcpy_s(_ReadBuf,1,&version,1);
		nRead = fn_ReadPkg(sockfd,_ReadBuf+1,_protocolLen-1);
		//fn_RYN_LOG_DEBUG(TAG,"nRead = %d, %s",nRead,"读取剩余协议头");
		// 网络异常或延时导致读取数据 < 0
		if (nRead < 0) {
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			if (errno == EINTR)
				goto __END_HANDLE;
			if(debug){
				fn_RYN_LOG_DEBUG(TAG,"%d read() error, errno = %d, error = %s,%s", getpid(), errno,strerror(errno),"读取剩余协议头");
			}
			nRet = ERRCODE_SCKCLOSE;
			goto __END_HANDLE;
			// 连接关闭
		}else if (nRead == 0) { // remote close
			fn_RYN_LOG_DEBUG(TAG,"Remote sockfd(%d) Close! %s",sockfd,"读取剩余协议头");
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			nRet = ERRCODE_SCKCLOSE;
			goto __END_HANDLE;
		}

		//PrintLutByte("移动前 ：",_ReadBuf,_protocolLen);

		// 循环右移1个字节
		//MoveRightByte(_ReadBuf,1);
		//PrintLutByte("移动后 ：",_ReadBuf,_protocolLen);


		PrintLutByte("协议头",_ReadBuf,_protocolLen);
		// 计算协议头16位首部校验和
		cksum = LutCkSum((Bit8 *)_ReadBuf,_protocolLen);
		if((Bit16)(~cksum) != 0xFFFF){
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			fn_RYN_LOG_INFO(TAG,"协议头校验和失败 cksum = %04X",cksum);
			goto __END_HANDLE;
		}

		/** 协议头字节转结构体 **/
		NewLutProtocolHead(_protocolHead,(Bit8 *)_ReadBuf,_protocolLen);

		// 读取16字节 AES KEY
		nRead = fn_ReadPkg(sockfd,(char *)_aesKey,sizeof(_aesKey));
		// 网络异常或延时导致读取数据 < 0
		if (nRead < 0) {
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			if (errno == EINTR)
				goto __END_HANDLE;
			if(debug){
				fn_RYN_LOG_DEBUG(TAG,"%d read() error, errno = %d, error = %s,%s", getpid(), errno,strerror(errno),"读取16字节 AES KEY");
			}
			goto __END_HANDLE;
			// 连接关闭
		}else if (nRead == 0) { // remote close
			fn_RYN_LOG_DEBUG(TAG,"Remote sockfd(%d) Close! %s",sockfd,"读取16字节 AES KEY");
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			goto __END_HANDLE;
		}

		// 读取16字节数据签名
		nRead = fn_ReadPkg(sockfd,(char *)_signature,sizeof(_aesKey));
		// 网络异常或延时导致读取数据 < 0
		if (nRead < 0) {
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			if (errno == EINTR)
				goto __END_HANDLE;
			if(debug){
				fn_RYN_LOG_DEBUG(TAG,"%d read() error, errno = %d, error = %s,%s", getpid(), errno,strerror(errno),"读取16字节数据签名");
			}
			goto __END_HANDLE;
			// 连接关闭
		}else if (nRead == 0) { // remote close
			fn_RYN_LOG_DEBUG(TAG,"Remote sockfd(%d) Close! %s",sockfd,"读取16字节数据签名");
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			goto __END_HANDLE;
		}

		// 计算加密数据长度
		_encrypDataLen = _protocolHead->total - _protocolLen - 32;
		_bodyDataLen = _encrypDataLen;
		MallocBuf(unsigned char,_encrypData,_encrypDataLen);
		MallocBuf(unsigned char,_bodyData,_bodyDataLen+1);

		do{
			// 读取主体数据
			nRead = fn_ReadPkg(sockfd,(char *)_encrypData + nTotalBodyRead,_encrypDataLen - nTotalBodyRead);
			nTotalBodyRead += nRead;
			//fn_RYN_LOG_DEBUG(TAG,"协议规定的数据长度：%d, 当前读取到的长度是：%d",_encrypDataLen,nRead);
			// 网络异常或延时导致读取数据 < 0
			if (nRead < 0 && nTotalBodyRead >= _encrypDataLen) {
				FreeBuf(_encrypData);
				FreeBuf(_bodyData);
				FreeBuf(_ReadBuf);
				FreeMem(_protocolHead);
				if (errno == EINTR)
					goto __END_HANDLE;
				if(debug){
					fn_RYN_LOG_DEBUG(TAG,"%d read() error, errno = %d, error = %s,%s", getpid(), errno,strerror(errno),"读取主体数据");
				}
				goto __END_HANDLE;
				// 连接关闭
			}else if (nRead == 0) { // remote close
				fn_RYN_LOG_DEBUG(TAG,"Remote sockfd(%d) Close! %s",sockfd,"读取主体数据");
				FreeBuf(_encrypData);
				FreeBuf(_bodyData);
				FreeBuf(_ReadBuf);
				FreeMem(_protocolHead);
				goto __END_HANDLE;
			}

			if(nTotalBodyRead >= _encrypDataLen){
				break;
			}else{
				continue;
			}
			////报文过长 导致一次性读取不全 所以要继续读
			//if(_encrypDataLen > 0 && _encrypDataLen != nRead && _encrypDataLen > nTotalBodyRead){
			//	//
			//	fn_RYN_LOG_DEBUG(TAG,"read to continue .. _encrypDataLen = [%d], nTotalBodyRead = [%d], nRead = [%d]",_encrypDataLen,nTotalBodyRead,nRead);
			//	//nRead = fn_ReadPkg(sockfd,(char *)_encrypData + nTotalBodyRead,_encrypDataLen - nTotalBodyRead);
			//	//fn_RYN_LOG_DEBUG(TAG,"读取完啦 nRead=%d",nRead);
			//}else{
			//	break;
			//}

		}while(1);

		PrintLutByte("收到加密数据",_encrypData,_encrypDataLen);
		//_encrypDataP = _encrypData;
		// 验证主体数据签名
		MD5Init(&md5ctx);
		MD5Update(&md5ctx,_encrypData,_encrypDataLen);
		MD5Final(digest,&md5ctx);
		PrintLutByte("signature",_signature,16);
		PrintLutByte("digestttt",digest,16);
		if(CompareArray(digest,_signature,0,16) != 0){
			FreeBuf(_encrypData);
			FreeBuf(_bodyData);
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			fn_RYN_LOG_INFO(TAG,"数据签名不一致,可能传输过程中被篡改");
			fn_RYN_LOG_INFO(TAG,"signature = %X , digest = %X",(unsigned int)_signature,(unsigned int)digest);
			goto __END_HANDLE;
		}

		PrintLutByte("AES KEY",_aesKey,16);
		PrintLutByte("AES PIV",IV_03X,16);
		PrintLutByte("解密之前主体数据",_encrypData,_encrypDataLen);
		// 解密数据主体
		AES_Init(_aesKey);
		AES_Decrypt(_bodyData,_bodyDataLen,_encrypData,_encrypDataLen,IV_03X);

		//DEBUG("加密后数据长度:%d\n",_encrypDataLen);
		PrintLutByte("解密之后主体数据",_bodyData,_encrypDataLen);
		//printf("文本表示主体数据：%s\n",_bodyData+2);

		memcpy_s(&_tt,sizeof(_tt),_bodyData,sizeof(_tt));
		_bit16 = (_tt[0]&0xFF)<<0x08 | (_tt[1]&0xFF);
		//_pureDataLen = _bit16 >> 0x08 | _bit16 << 0x08;
		//fn_RYN_LOG_DEBUG(TAG,"解密之后计算得出的长度:%d",_bit16);//长度有时不准 应该是解密失败了. 改用固定的长度吧。fix by jiangwx 20181208
		_pureDataLen = _bit16;
		if(_bit16 > 8192 || _bit16 <= 0) {//最大8k _bit16 > 8192
			char *ppureData = (char *)_bodyData+sizeof(Bit16);
			_pureDataLen = strlen(ppureData);
			fn_RYN_LOG_DEBUG(TAG,"计算得出的数据长度: %d, 原长度:%d",_pureDataLen,_bit16);
		}

		MallocBuf(char,_pureData,_pureDataLen+20);
		memcpy_s(_pureData,_pureDataLen,_bodyData+sizeof(Bit16),_pureDataLen);

		//判断是否为JSON
		if(_pureData[0] != '{' || _pureData[_pureDataLen-1] != '}'){
			fn_RYN_LOG_DEBUG(TAG,"pureData = %s",_pureData);
			fn_RYN_LOG_DEBUG(TAG,"解密失败啦啦啦...");
			FreeBuf(_pureData);
			FreeBuf(_encrypData);
			FreeBuf(_bodyData);
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			goto __END_HANDLE;
		}

		pRoot = fn_cJSON_Parse(_pureData);
		if(!pRoot){
			fn_RYN_LOG_WARN(TAG,"fn_cJSON_Parse 失败, _pureData = %s",_pureData);
			FreeBuf(_pureData);
			FreeBuf(_encrypData);
			FreeBuf(_bodyData);
			FreeBuf(_ReadBuf);
			FreeMem(_protocolHead);
			fn_RYN_LOG_INFO(TAG,"fn_cJSON_Parse 失败, _pureData = %s",_pureData);
			fn_cJSON_Delete(pRoot);
			fn_RYN_LOG_WARN(TAG,"fn_cJSON_Parse 该释放的时候就释放");

			goto __END_HANDLE;
		}

		//nTimestamp = (long)fn_cJSON_GetObjectItem(pRoot,"nTimestamp")->valuedouble;
		//szNonce = fn_cJSON_GetObjectItem(pRoot,"szNonce")->valuestring;
		//szUserAgentSerial = fn_cJSON_GetObjectItem(pRoot,"szUserAgentSerial")->valuestring;
		errCode = fn_cJSON_GetObjectItem(pRoot,"errCode")?fn_cJSON_GetObjectItem(pRoot,"errCode")->valueint:fn_cJSON_GetObjectItem(pRoot,"errorCode")->valueint;

		//fn_RYN_LOG_DEBUG(TAG,"HandleSacPackage errCode:%d",errCode);

#ifdef WIN32
		if(1){
			char *_tmp;
			//MallocBuf(char,_tmp,_pureDataLen);
			fn_Utf8_to_Ansii(_pureData,&_tmp);
			memset(szRtJson,0,_pureDataLen);
			memcpy_s(szRtJson, _pureDataLen,_tmp,_pureDataLen);
			*nRtJsonLen = _pureDataLen;
			FreeBuf(_tmp);
		}
#else
		memcpy_s(szRtJson,_pureDataLen,_pureData,_pureDataLen);
		*nRtJsonLen = _pureDataLen;
#endif
		FreeBuf(_pureData);

		nRet = errCode;

		if(1){
			int nnSac = 0;
			nnSac = _protocolHead->sac;
			nnSac = (nnSac >> 24 &0xFF) | (nnSac << 24) | (nnSac >> 8 &0xFF00) |(nnSac << 8 &0xFF0000);
			*nSac = nnSac;
		}

		FreeBuf(_encrypData);
		FreeBuf(_bodyData);
		FreeBuf(_ReadBuf);
		FreeMem(_protocolHead);
		//fn_RYN_LOG_DEBUG(TAG,"HandleSacPackage:%s",cJSON_GetErrorPtr());
		fn_cJSON_Delete(pRoot);
		//FreeBuf(szNonce);
		//FreeBuf(szUserAgentSerial);

		nRet = ERRCODE_OK;
		return nRet;

		// 读超时
	}else if(nReadSta == -1){
		//fn_RYN_LOG_DEBUG(TAG,"End HandleSacPackage");
		if(debug){
			fn_RYN_LOG_DEBUG(TAG,"nReadSta == -1,Select Timeout... errno = %d",errno);
		}
		nRet = ERRCODE_READ_TIMEOUT;
		goto __END_HANDLE;
		// 异常退出
	}else{
		fn_RYN_LOG_DEBUG(TAG,"ERRCODE_SCKEXIT nReadSta = %d,errno = %d",nReadSta,errno);
		nRet = ERRCODE_SCKEXIT;
		goto __END_HANDLE;
	}

__END_HANDLE:
	return nRet;
}

/** 发送数据包到服务器 兼容 0.3.x 版本 MainLoop ***/
void *LutServiceLoop(Approxy4cST_t *approxy4cST){
	//int debug = 0;
	int network_sta = 0;//网络状态 0网络不联通 1网络恢复
	int sockfd = 0;//,nRet = 0;
	//int dataLen = 0;
	int nServerIte = 0;
	//char pDataLen[4];
	static unsigned char svrHostIpV4[64] = {0};
	int nSvrHostIpV4Len = 0;
	//unsigned char *pData;
	//unsigned char *pPlainText = NULL;
	//重连时间 单位毫秒
	//unsigned int n_reconnect_interval = 5000;
	//char _reconnect_interval[1024] = {0};

	int nWriteSta = 0;
	char *szSessionID = NULL;
	//char *szUserAgent = NULL;
	//char *szUid = NULL;
	//char *szSid = NULL;
	//char *szAccessToken = NULL;
	ServerST_t *pServerST = NULL;
	int serverPort = 0;
	int approxy4c_index = 0;

	approxy4c_index = approxy4cST_t_count;

	do{
		// 心跳包计数器
		int sacSHBCounter = 20;
		MallocMem(ServerST_t,pServerST);
		memset(pServerST->serverIP,0,sizeof(pServerST->serverIP));
		memcpy_s(pServerST->serverIP,strlen(approxy4cST->pServerSTArray[nServerIte]->serverIP),approxy4cST->pServerSTArray[nServerIte]->serverIP,strlen(approxy4cST->pServerSTArray[nServerIte]->serverIP));
		pServerST->serverPort = approxy4cST->pServerSTArray[nServerIte]->serverPort;
        
        fn_RYN_LOG_INFO(TAG,"serverIP: %s",(unsigned char *)pServerST->serverIP);
        vTaskDelay(pdMS_TO_TICKS(6000));

		GetHostByName(svrHostIpV4,(unsigned char *)pServerST->serverIP);
		nSvrHostIpV4Len = strlen((char *)svrHostIpV4);
		serverPort = pServerST->serverPort;
		fn_RYN_LOG_INFO(TAG,"域名解析 ：%s => %s",pServerST->serverIP,svrHostIpV4);
		FreeMem(pServerST);

		fn_RYN_LOG_INFO(TAG,"正在连接... %s:%d, Host.len:[%d]",svrHostIpV4,serverPort,nSvrHostIpV4Len);
		sockfd = fn_NewSocket(svrHostIpV4,nSvrHostIpV4Len,serverPort);

		fn_RYN_LOG_INFO(TAG,"sockfd ... %d",sockfd);
		approxy4cST->stayRun = 1;
		if(sockfd == -1){
			// if(approxy_cfg_st->switch_running == 0) {
			// 	approxy4cST->nUserLoginStatus = RYN_LOGIN_STA_TIMEOUT;
			// 	break;
			// }

			fn_RYN_LOG_WARN(TAG,"network error,please wait 5 seconds to reconnect...");

			// 网络断开
			network_sta = 0;
			onNetworkSta(network_sta);

			approxy4cST->nUserLoginStatus = RYN_LOGIN_STA_TIMEOUT;

			vTaskDelay(pdMS_TO_TICKS(5000));

			fn_RYN_LOG_INFO(TAG,"&cond timeout start reconnet...");

			approxy4cST->nGlConnected = LUT_DISCONNECTED;

			if(nServerIte + 1 >= approxy4cST->nServerSTArraySize){
				nServerIte = 0;
			}else{
				nServerIte ++;
			}
			continue;
		}

		//复制当前连接的地址给 全局变量
		if (approxy4cST->pGlSvrHost == NULL || approxy4cST->nGlSvrHostLen == 0 || approxy4cST->nGlSvrPort == 0) {
			if(approxy4cST->pGlSvrHost)
				FreeBuf(approxy4cST->pGlSvrHost);
			
			MallocBuf(unsigned char, approxy4cST->pGlSvrHost, 48);
			//fn_RYN_LOG_INFO(TAG,"nSvrHostIpV4Len:%d",nSvrHostIpV4Len);
			memcpy_s(approxy4cST->pGlSvrHost, nSvrHostIpV4Len, svrHostIpV4,nSvrHostIpV4Len);
			approxy4cST->nGlSvrPort = serverPort;
			approxy4cST->nGlSvrHostLen = nSvrHostIpV4Len;
			
		}
		memset(approxy4cST->glLoopServiceAddr,0,sizeof(approxy4cST->glLoopServiceAddr));
		sprintf_s((char *)approxy4cST->glLoopServiceAddr,sizeof(approxy4cST->glLoopServiceAddr),"%s:%d",approxy4cST->pServerSTArray[nServerIte]->serverIP,approxy4cST->pServerSTArray[nServerIte]->serverPort);
		fn_RYN_LOG_INFO(TAG,"当前连接地址:%s, svrHostIpV4:%s",approxy4cST->glLoopServiceAddr,svrHostIpV4);
		//fn_RYN_LOG_DEBUG(TAG,"WaitSvrPkg sockfd:%d,pkglen = %d",sockfd,pkgLen);
		approxy4cST->nGlSvrSockfd = sockfd;

		nWriteSta = fn_WriteTimeout(sockfd,SHB_READ_TIME);
		//fn_RYN_LOG_INFO(TAG,"nWriteSta ... %d",nWriteSta);
		if(nWriteSta == 0){
			// 已经连接到服务器
			cJSON *pSynJson = NULL;
			LutPackage_t * _lutPackage = NULL;
			char * szSynCode = NULL;
			char * synCode = NULL;
			int nRet = 0;
			int nSac = 0;

			char * szRtJson = NULL;
			int nRtJsonLen = 0;
			char * szTmpSessionID = NULL;
			char * szTmpUserAgent = NULL;
			char * szTmpUid = NULL;
			char * szTmpSid = NULL;
			char * szTmpAccessToken = NULL;
			char * szTmpWebCtxPath = NULL;
			cJSON * pRoot = NULL;

			char *szUserAgent = NULL;
			char *szUid = NULL;
			char *szSid = NULL;
			char *szAccessToken = NULL;
			char *szWebCtxPath = NULL;

			// 网络恢复
			network_sta = 1;
			onNetworkSta(network_sta);
			fn_RYN_LOG_DEBUG(TAG,"网络恢复1. 发送握手数据包 SAC_SYN");

			// 1. 发送握手数据包 SAC_SYN
			MallocMem(LutPackage_t,_lutPackage);
			NewLutSacSYNPackage(_lutPackage);

			fn_WritePkg(sockfd,(char *)_lutPackage->_LutPackage,_lutPackage->_LutPackageLen);
			FreeBuf(_lutPackage->_LutPackage);
			FreeMem(_lutPackage);
			MallocBuf(char,szRtJson,RTJsonLen);
			nRet = HandleSacPackage(&nSac,szRtJson,&nRtJsonLen,sockfd);
			fn_RYN_LOG_INFO(TAG,"SAC_SYN ... nRet = %d",nRet);
			if(nRet != ERRCODE_OK){
				FreeBuf(szRtJson);
				goto __END_WHILE;
			}

			fn_RYN_LOG_INFO(TAG,"SAC_SYN ... szRtJson = %s",szRtJson);
			pSynJson = fn_cJSON_Parse(szRtJson);
			synCode = fn_cJSON_GetObjectItem(pSynJson,"synCode")!=NULL?fn_cJSON_GetObjectItem(pSynJson,"synCode")->valuestring:NULL;
			fn_RYN_LOG_INFO(TAG,"SYN synCode:%s",synCode);
			if (synCode && strlen(synCode) > 0)
			{
				MallocBuf(char,szSynCode,strlen(synCode) + 1);
				memcpy_s(szSynCode,strlen(synCode),synCode,strlen(synCode));
			}else{
				MallocBuf(char,szSynCode,1);
			}
			FreeBuf(szRtJson);
			fn_cJSON_Delete(pSynJson);
			fn_RYN_LOG_INFO(TAG,"SAC_SAU1 synCode:%s",szSynCode);

			// 2. 发送授权数据包 SAC_SAU
			MallocMem(LutPackage_t,_lutPackage);
			NewLutSacSAUPackage(_lutPackage,(Bit8 *)approxy4cST->pGlUserName,(Bit8 *)approxy4cST->pGlPaasword,(Bit8 *)szSynCode);
			fn_RYN_LOG_INFO(TAG,"SAC_SAU2 synCode:%d",_lutPackage->_LutPackageLen);
			if(1){
				int nWrite = 0;
				nWrite = fn_WritePkg(sockfd,(char *)_lutPackage->_LutPackage,_lutPackage->_LutPackageLen);
				fn_RYN_LOG_INFO(TAG,"SAC_SAU2 nWrite:%d",nWrite);
			}
			

			FreeBuf(szSynCode);
			FreeBuf(_lutPackage->_LutPackage);
			FreeMem(_lutPackage);
			MallocBuf(char,szRtJson,RTJsonLen);
			
			nRet = HandleSacPackage(&nSac,szRtJson,&nRtJsonLen,sockfd);
			fn_RYN_LOG_INFO(TAG,"SAC_SAU ... nRet = %d,nRtJsonLen = %d",nRet,nRtJsonLen);
			if(nRet != ERRCODE_OK){
				FreeBuf(szRtJson);
				goto __END_WHILE;
			}
			fn_RYN_LOG_INFO(TAG,"SAU JSON:%s",szRtJson);

			pRoot = fn_cJSON_Parse(szRtJson);

			if(1201 == fn_cJSON_GetObjectItem(pRoot,"errCode")->valueint
				&& fn_cJSON_GetObjectItem(pRoot,"szSessionID") == NULL){
					FreeBuf(szRtJson);
					fn_cJSON_Delete(pRoot);
					fn_RYN_LOG_INFO(TAG,"授权失败,用户名和密码不匹配!");

					/***********************************************************************/
					//登录失败,回调JNI Java,响应onLoginFail事件
					/************************************************************************/
					onLoginFail(approxy4cST->pGlUserName,strlen(approxy4cST->pGlUserName));

					approxy4cST->nUserLoginStatus = RYN_LOGIN_STA_DENY;
					approxy4cST->stayRun = 0;
					goto __END_WHILE;
			}

			szTmpSessionID = fn_cJSON_GetObjectItem(pRoot,"szSessionID") != NULL ? fn_cJSON_GetObjectItem(pRoot,"szSessionID")->valuestring : NULL;
			if(!szTmpSessionID){
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			szTmpUserAgent = fn_cJSON_GetObjectItem(pRoot,"szUserAgentSerial") != NULL ? fn_cJSON_GetObjectItem(pRoot,"szUserAgentSerial")->valuestring : NULL;
			fn_RYN_LOG_INFO(TAG,"login szUserAgentSerial = %s",szTmpUserAgent != NULL ? szTmpUserAgent : "NULL");

			if(!szTmpUserAgent){
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			szTmpUid = fn_cJSON_GetObjectItem(pRoot,"szUid") != NULL ? fn_cJSON_GetObjectItem(pRoot,"szUid")->valuestring : NULL;
			fn_RYN_LOG_INFO(TAG,"login szUid = %s",szTmpUid != NULL ? szTmpUid : "NULL");

			if(!szTmpUid){
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			szTmpSid = fn_cJSON_GetObjectItem(pRoot,"szSid") != NULL ? fn_cJSON_GetObjectItem(pRoot,"szSid")->valuestring : NULL;
			fn_RYN_LOG_INFO(TAG,"login szSid = %s",szTmpSid != NULL ? szTmpSid : "NULL");

			if(!szTmpSid){
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			szTmpAccessToken = fn_cJSON_GetObjectItem(pRoot,"szAccessToken") != NULL ? fn_cJSON_GetObjectItem(pRoot,"szAccessToken")->valuestring : NULL;
			fn_RYN_LOG_INFO(TAG,"login szAccessToken = %s",szTmpAccessToken != NULL ? szTmpAccessToken : "NULL");

			if(!szTmpAccessToken){
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			szTmpWebCtxPath = fn_cJSON_GetObjectItem(pRoot, "szWebCtxPath")->valuestring;
			fn_RYN_LOG_INFO(TAG,"login szWebCtxPath = %s", szTmpWebCtxPath);

			if (!szTmpWebCtxPath) {
				FreeBuf(szRtJson);
				fn_cJSON_Delete(pRoot);
				goto __END_WHILE;
			}

			MallocBuf(char,szSessionID,strlen(szTmpSessionID)+1);
			memcpy_s(szSessionID,strlen(szTmpSessionID),szTmpSessionID,strlen(szTmpSessionID));

			MallocBuf(char,szUserAgent,strlen(szTmpUserAgent)+1);
			memcpy_s(szUserAgent,strlen(szTmpUserAgent),szTmpUserAgent,strlen(szTmpUserAgent));

			MallocBuf(char,szUid,strlen(szTmpUid)+1);
			memcpy_s(szUid,strlen(szTmpUid),szTmpUid,strlen(szTmpUid));

			MallocBuf(char,szSid,strlen(szTmpSid)+1);
			memcpy_s(szSid,strlen(szTmpSid),szTmpSid,strlen(szTmpSid));

			MallocBuf(char,szAccessToken,strlen(szTmpAccessToken)+1);
			memcpy_s(szAccessToken,strlen(szTmpAccessToken),szTmpAccessToken,strlen(szTmpAccessToken));

			MallocBuf(char,szWebCtxPath,strlen(szTmpWebCtxPath)+1);
			memcpy_s(szWebCtxPath,strlen(szTmpWebCtxPath),szTmpWebCtxPath,strlen(szTmpWebCtxPath));

			FreeBuf(szRtJson);
			fn_cJSON_Delete(pRoot);

			/** 授权成功，将在下方循环中发送心跳数据包 **/
			fn_RYN_LOG_INFO(TAG,"授权成功,将进行数据包传送!!");

			/***********************************************************************/
			//将 szSessionID 拷贝到 pGlHbSeKey 作为授权识别序列号
			//在v0.2.x时 pGlHbSeKey 是在登录成功之后服务器的授权码
			//在v0.3.x时 pGlHbSeKey 是会话ID，可以进行授权操作
			/************************************************************************/
			//FreeBuf(pGlHbSeKey);
			//MallocBuf(unsigned char ,pGlHbSeKey,strlen(szSessionID)+1);
			memset(approxy4cST->pGlHbSeKey, 0, sizeof(approxy4cST->pGlHbSeKey));
			memcpy_s(approxy4cST->pGlHbSeKey,strlen(szSessionID),szSessionID,strlen(szSessionID));

			//复制到 gl_uidSTR
			memset(approxy4cST->gl_uidSTR, 0, sizeof(approxy4cST->gl_uidSTR));
			memcpy_s(approxy4cST->gl_uidSTR, strlen(szUid), szUid, strlen(szUid));

			//复制到 gl_sidSTR
			memset(approxy4cST->gl_sidSTR, 0, sizeof(approxy4cST->gl_sidSTR));
			memcpy_s(approxy4cST->gl_sidSTR, strlen(szSid), szSid, strlen(szSid));

			//复制到 gl_accessTokenSTR
			memset(approxy4cST->gl_accessTokenSTR, 0, sizeof(approxy4cST->gl_accessTokenSTR));
			memcpy_s(approxy4cST->gl_accessTokenSTR, strlen(szAccessToken), szAccessToken,strlen(szAccessToken));

			//复制到 gl_webCtxPathSTR
			memset(approxy4cST->gl_webCtxPathSTR, 0, sizeof(approxy4cST->gl_webCtxPathSTR));
			memcpy_s(approxy4cST->gl_webCtxPathSTR, strlen(szWebCtxPath), szWebCtxPath,strlen(szWebCtxPath));

			//复制到 gl_loginName
			memset(approxy4cST->gl_loginName, 0, sizeof(approxy4cST->gl_loginName));
			memcpy_s(approxy4cST->gl_loginName, strlen(approxy4cST->pGlUserName), approxy4cST->pGlUserName,strlen(approxy4cST->pGlUserName));

			/***********************************************************************/
			//登录成功,回调JNI Java,响应onLoginSucc事件
			/************************************************************************/
			onLoginSucc(approxy4cST->pGlUserName,strlen(approxy4cST->pGlUserName),szUserAgent,strlen(szUserAgent),szUid,strlen(szUid),szSid,strlen(szSid),szAccessToken,strlen(szAccessToken),szWebCtxPath,strlen(szWebCtxPath));
			
			/** 更新UserLogin状态 ，RYnAPProxy登录时需要使用 **/
			approxy4cST->nUserLoginStatus = RYN_LOGIN_STA_RUNNING;
			approxy4cST->nGlSvrSockfd = sockfd;

			/** 保持持续运行 网络连接断开之后 自动重连 **/
			approxy4cST->stayRun = 1;

			approxy4cST->channelID = CHANNEL_BEGIN + approxy4c_index;
			approxy4cST_t_s[approxy4c_index] = approxy4cST;
			approxy4cST_t_count = approxy4c_index +1;
			fn_RYN_LOG_DEBUG(TAG,"channelID: %d",approxy4cST->channelID);

			FreeBuf(szUid);
			FreeBuf(szSid);
			FreeBuf(szAccessToken);
			FreeBuf(szSessionID);
			FreeBuf(szUserAgent);

		}else {
			fn_RYN_LOG_INFO(TAG,"nWriteSta = %d,写超时!!",nWriteSta);
			CloseRYnSocket(sockfd);
			goto __END_WHILE;
		}

		for(;;){
			if(strlen((char *)approxy4cST->pGlHbSeKey) == 0){
				fn_RYN_LOG_DEBUG(TAG,"szSessionID = %s",approxy4cST->pGlHbSeKey);
				break;
			}else{
				char * szRtJson = NULL;
				int nRtJsonLen = 0;
				int nSac = 0;

				LutPackage_t * _lutPackage = NULL;
				int nRet = 0;

				//fn_RYN_LOG_INFO(TAG,"HandleSacPackage AA = %d",nRet);

				// 3. 主线程等待服务端返回数据包（SAC_SHB,SAC_SDA,SAC_SCM）
				MallocBuf(char,szRtJson,MAX_LOOP_RECV_BUF);
				nRet = HandleSacPackage(&nSac,szRtJson,&nRtJsonLen,sockfd);
				szRtJson[MAX_LOOP_RECV_BUF-1] = 0;//最后一个字节必须要是 '\0'

				//fn_RYN_LOG_INFO(TAG,"HandleSacPackage FF nRet = %d",nRet);
				// 3.1 异常退出（未知异常）
				if(nRet == ERRCODE_SCKEXIT){
					fn_RYN_LOG_DEBUG(TAG,"Socket Exit ,Return Nothing !! %s",szRtJson);
					FreeBuf(szRtJson);
					break ;
				}

				// 3.1 异常退出（服务器关闭）
				if(nRet == ERRCODE_SCKCLOSE){
					fn_RYN_LOG_DEBUG(TAG,"Socket Close ,Return Nothing !! %s",szRtJson);
					FreeBuf(szRtJson);
					break ;
				}
				// 3.1. 异常退出
				if(nRet == -1){
					fn_RYN_LOG_DEBUG(TAG,"Socket Server Close Return 0 Data !! %s",szRtJson);
					FreeBuf(szRtJson);
					break;
				}

				// 4. 接收到心跳数据包返回
				if(nSac == SAC_SHB && nRet == ERRCODE_OK){
					//if(ShowSecurityData)
					// 在任务中定期检查
					UBaseType_t watermark = uxTaskGetStackHighWaterMark(NULL);
					ESP_LOGI(TAG, "Stack free: %u words (%u bytes) 可用内存: %.2f kb", watermark, watermark * 4,(float)esp_get_free_heap_size()/1024);
					fn_RYN_LOG_INFO(TAG,"Recv SAC_SHB Return Data ! %s",szRtJson);
					FreeBuf(szRtJson);
					sacSHBCounter = SHB_MANAGER_COUNTER;

					onRecvHeartBeat();
					continue;
				}

				// 4.1 接收到授权超时数据包返回
				if(nSac == SAC_SHB && nRet == ERRCODE_SIDTMOUT){
					if(ShowSecurityData)
						fn_RYN_LOG_DEBUG(TAG,"Recv SAC_SHB ERRCODE_SIDTMOUT Return Data ! %s",szRtJson);
					FreeBuf(szRtJson);
					sacSHBCounter = 0;
					break;
				}

				// 4.2 接收到服务器心跳授权超时数据包返回
				if(nSac == SAC_SHB_TIMEOUT && nRet == ERRCODE_OK){
					if(ShowSecurityData)
						fn_RYN_LOG_DEBUG(TAG,"Recv SAC_SHB_TIMEOUT ERRCODE_SIDTMOUT Return Data ! %s",szRtJson);
					FreeBuf(szRtJson);
					sacSHBCounter = 0;
					break;
				}
				// 5. 接收到指令数据包返回
				if(nSac == SAC_SCM && nRet == ERRCODE_OK){
					SacSCMSocket_t * sacScmSocket = NULL;
					if(ShowSecurityData)
						fn_RYN_LOG_DEBUG(TAG,"Recv SAC_SCM Return Data ! %s",szRtJson);
					// Handle SAC_SCM
					MallocMem(SacSCMSocket_t,sacScmSocket);
					MallocBuf(unsigned char,sacScmSocket->szJson,nRtJsonLen+1);
					memcpy_s(sacScmSocket->szJson,nRtJsonLen,szRtJson,nRtJsonLen);

					if(0){
                        // if(xTaskCreate(HandleSacSCMWorker, "HandleSacSCMWorker", 4096,  (void *)approxy4cST, 3, NULL) !=0 ){
                        //    fn_RYN_LOG_INFO(TAG,"HandleSacSCMWorker Fail to create thread!");
                        // }
					}
					FreeBuf(szRtJson);
					continue;
				}

				// 6. 接收到数据数据包返回
				if(nSac == SAC_SDA && nRet == ERRCODE_OK){
					fn_RYN_LOG_DEBUG(TAG,"Recv SAC_SDA Return Data ! %s",szRtJson);
					FreeBuf(szRtJson);
					continue;
				}


				// 7. 接收到打洞数据包返回
				if(nSac == SAC_RDG && nRet == ERRCODE_OK){
					fn_RYN_LOG_DEBUG(TAG,"Recv SAC_RDG Return Data ! %s",szRtJson);
					fn_RYN_LOG_DEBUG(TAG,"Client A Will DigHole!!");
					// szRtJson = B端公网IP和Port 和 P2P服务中转地址
					if(0){
					}
					FreeBuf(szRtJson);
					continue;
				}

				// 8. 接收到IM推送数据包返回
				if(nSac == SAC_IM && nRet == ERRCODE_OK){
					fn_RYN_LOG_DEBUG(TAG,"Recv SAC_IM Return Data ! %s",strlen(szRtJson)>800?"Too long...":szRtJson);
					if(1){
						
						IMHandleST_t *imHandleST = NULL;
						int nJsonLen = 0;
						szRtJson[MAX_LOOP_RECV_BUF-1] = 0;
						nJsonLen = strlen(szRtJson);
						MallocMem(IMHandleST_t,imHandleST);
						MallocBuf(char,imHandleST->json,nJsonLen+1);
						memcpy_s(imHandleST->json,nJsonLen,szRtJson,nJsonLen);
						imHandleST->json_len = nJsonLen;
						imHandleST->channelID = approxy4cST->channelID;

						// fn_RYN_LOG_INFO(TAG,"imHandleST->channelID: %d",imHandleST->channelID);
						// if(pthread_create(&_imThread,NULL,IMHandle,imHandleST) != 0){
						// 	fn_RYN_LOG_INFO(TAG,"IMHandle Fail to create thread!");
						// }
						// pthread_detach(_imThread);

						if(1){
							
							//xTaskCreate(IMHandle, "esp_main_task", 4096, imHandleST, 3, NULL);
							
						}
						
						//fn_RYN_LOG_INFO(TAG,"IMHandle：可用堆内存：%.2f kb",(float)esp_get_free_heap_size()/1024);
						IMHandle(imHandleST);

					}
					FreeBuf(szRtJson);
					continue;
				}

				// 读超时,固定时间内服务器无数据返回
				if(nRet == ERRCODE_READ_TIMEOUT){
					sacSHBCounter--;
					//fn_RYN_LOG_DEBUG(TAG,"sacSHBCounter: %d",sacSHBCounter);
					// 心跳包计数器到达计数点,客户端网服务器主动发送心跳包
					if(sacSHBCounter <= 0){
						// 主线程发送心跳数据包 SAC_SHB
						MallocMem(LutPackage_t,_lutPackage);
						NewLutSacSHBPackage(_lutPackage,(Bit8 *)approxy4cST->pGlHbSeKey);
						fn_WritePkg(sockfd,(char *)_lutPackage->_LutPackage,_lutPackage->_LutPackageLen);
						FreeBuf(_lutPackage->_LutPackage);
						FreeMem(_lutPackage);
						sacSHBCounter = SHB_MANAGER_COUNTER;
					}
				}

				//fn_RYN_LOG_DEBUG(TAG,"SAC Package szRtJson = %s ==> nRet = %d",szRtJson,nRet);
				FreeBuf(szRtJson);
				if(approxy4cST->stayRun == 0) break;
				if(approxy4c_needExit == 1) {
					approxy4cST->stayRun = 0;
					break;
				}
				//nUserRunningSta = USER_RUNNING_STA_N;
				//break;
			}
		}//end for(;;)
		fn_RYN_LOG_DEBUG(TAG,"end for(;;) break;");
__END_WHILE:
		//FreeBuf(szSessionID);
		//FreeBuf(szUserAgent);
		//FreeBuf(szAccessToken);
		//FreeBuf(szSid);
		//FreeBuf(szUid);

		if(sockfd > 0)
			CloseRYnSocket(sockfd);
		fn_RYN_LOG_DEBUG(TAG,"nUserRunningSta:%d ,stayRun: %d",approxy4cST->nUserRunningSta,approxy4cST->stayRun);
	}while(approxy4cST->nUserRunningSta && approxy4cST->stayRun);
	// pthread_mutex_destroy(&mutex);
	// pthread_cond_destroy(&cond);
	fn_RYN_LOG_INFO(TAG,"WaitSvrPkg end!!:%d",sockfd);
	//FreeBuf(pServerST);
	return 0;
}

/************************************************************************/
/* 发送SCM指令到服务器(心跳服务器)                                        */
/************************************************************************/
int SendSacSCMPackageToBeat(char *szRtJson,int *nRtJson,Approxy4cST_t *approxy4cST, char *_szSCM,char *_szSCMDA){
	//PrintByteArray("ToBeat:",approxy4cST->pGlSvrHost,24);
	//fn_RYN_LOG_INFO(TAG,"ToBeat: %s:%d, len: %d",(char *)approxy4cST->pGlSvrHost,approxy4cST->nGlSvrPort,approxy4cST->nGlSvrHostLen);
	// 获取Beat地址
	if(!approxy4cST || approxy4cST->pGlSvrHost == NULL || approxy4cST->nGlSvrHostLen == 0 || approxy4cST->nGlSvrPort == 0) return -1;
	return SendSacSCMPackageToHost(szRtJson,nRtJson,approxy4cST,_szSCM,_szSCMDA,(char *)approxy4cST->pGlSvrHost,approxy4cST->nGlSvrHostLen,approxy4cST->nGlSvrPort);
}


/************************************************************************/
/* 发送SCM指令到服务器 兼容v0.3.x                                        */
/************************************************************************/
int SendSacSCMPackageToHost(char *szRtJson,int *nRtJson,Approxy4cST_t *approxy4cST,char *_szSCM,char *_szSCMDA,char *szHost,int nHostLen,int nPort){
	LutPackage_t *_lutPackage = NULL;
	char * szBuf = NULL;
	int nBufLen = 1024 * 2;
	int nReadSta = 0,nRead = 0;
	int sockfd = 0;
	int nSac = 0;
	int nRet = 0;
	cJSON * pRoot = NULL;
	char * szReturn = NULL;
	
	// char * szReturnSplit = NULL;

	// unsigned char host[20] = {0};
	// char *dest[32] ={0};
	// int nDestLen = 0;

	// if(!approxy4cST->pGlHbSeKey) return -1;

	// if(!(approxy4cST->pGlSvrHost)) return -1;

	if(NULL == szHost) return  -1;

	// 连接CoreData地址 获取UserPort
	//PrintByteArray("szHost:",szHost,24);
	//fn_RYN_LOG_INFO(TAG,"szHost: %s, nPort: %d, hostLen:%d",szHost,nPort,nHostLen);
	//fn_RYN_LOG_INFO(TAG,"可用内存：%.2f kb",(float)esp_get_free_heap_size()/1024);

	// if(approxy4cST->nGlSvrSockfd <= 0){
		sockfd = fn_NewSocket((unsigned char *)szHost,nHostLen,nPort);
		if(sockfd <= 0) {
			fn_RYN_LOG_INFO(TAG,"Can't Create New Socket!! !!GetLastError = %d",GetLastError());
			return -1;
		}
		// approxy4cST->nGlSvrSockfd = sockfd;
	// }
	
	MallocMem(LutPackage_t,_lutPackage);
	NewLutSacSCMPackage(_lutPackage,(Bit8 *)_szSCM,(Bit8 *)_szSCMDA,(Bit8 *)approxy4cST->pGlHbSeKey);
	nReadSta = fn_WritePkg(sockfd,(char *)_lutPackage->_LutPackage,_lutPackage->_LutPackageLen);
	FreeBuf(_lutPackage->_LutPackage);
	FreeMem(_lutPackage);

	MallocBuf(char,szBuf,nBufLen);
	nRet = HandleSacPackage(&nSac,szBuf,&nRead,sockfd);
#ifdef WIN32
	if(0){
		char *_tmp = NULL;
		//MallocBuf(char,_tmp,nRead * 3);
		fn_Utf8_to_Ansii(szBuf,&_tmp);
		memset(szBuf,0,nBufLen);
		memcpy_s(szBuf, nRead * 3,_tmp,nRead * 3);
		FreeBuf(_tmp);
	}
#endif

	pRoot = fn_cJSON_Parse(szBuf);
	if(pRoot == NULL){
		FreeBuf(szBuf);
		return -1;
	}
	szReturn = fn_cJSON_GetObjectItem(pRoot,"szReturn")?fn_cJSON_GetObjectItem(pRoot,"szReturn")->valuestring:NULL;

	if(ShowSecurityData){
		fn_RYN_LOG_DEBUG(TAG,"Recv RUT Package = %s",szReturn);
    }
	if(szReturn){
		memcpy_s(szRtJson,strlen(szReturn),szReturn,strlen(szReturn));
		*nRtJson = strlen(szReturn);
	}else{
		*nRtJson = 0;
	}

	fn_cJSON_Delete(pRoot);
	FreeBuf(szBuf);

	//MallocMem(LutPackage_t,_lutPackage);
	//NewLutSacSNUPackage(_lutPackage,(Bit8 *)SAC_SNU_SocketClose,(Bit8 *)"");
	//nReadSta = fn_WritePkg(sockfd,(char *)_lutPackage->_LutPackage,_lutPackage->_LutPackageLen);
	//FreeBuf(_lutPackage->_LutPackage);
	//FreeMem(_lutPackage);

	CloseRYnSocket(sockfd);
	return 0;
}

/** 获取用户ID **/
int GetUidSTR(char *szUidSTR,int *pLen){
	Approxy4cST_t *approxy4cST = NULL;
	int nUidLen = 0;
	if (approxy4cST_t_count > 0) {
		approxy4cST = approxy4cST_t_s[0];
	}else{
		*pLen = 0;
		return -1;
	}
	nUidLen = (int)strlen(approxy4cST->gl_uidSTR);
	if(nUidLen > 0){
		memcpy_s(szUidSTR,nUidLen,approxy4cST->gl_uidSTR,nUidLen);
		*pLen = nUidLen;
		return 0;
	}else{
		return -1;
	}
}


/** 获取用户openID **/
int GetLoginNameSTR(char *szSTR,int *pLen){
	Approxy4cST_t *approxy4cST = NULL;
	int nUidLen = 0;
	if (approxy4cST_t_count > 0) {
		approxy4cST = approxy4cST_t_s[0];
	}else{
		*pLen = 0;
		return -1;
	}
	nUidLen = (int)strlen(approxy4cST->gl_loginName);
	if (nUidLen > 0) {
		memcpy_s(szSTR, nUidLen, approxy4cST->gl_loginName, nUidLen);
		*pLen = nUidLen;
		return 0;
	} else {
		return -1;
	}
}

/** 获取用户openID **/
int GetSidSTR(char *szSidSTR,int *pLen){
	Approxy4cST_t *approxy4cST = NULL;
	int nUidLen = 0;
	if (approxy4cST_t_count > 0) {
		approxy4cST = approxy4cST_t_s[0];
	}else{
		*pLen = 0;
		return -1;
	}
	nUidLen = (int)strlen(approxy4cST->gl_sidSTR);
	if (nUidLen > 0) {
		memcpy_s(szSidSTR, nUidLen, approxy4cST->gl_sidSTR, nUidLen);
		*pLen = nUidLen;
		return 0;
	} else {
		return -1;
	}
}
int GetAccessTokenSTR(char *szAccessTokenSTR,int *pLen){
	Approxy4cST_t *approxy4cST = NULL;
	int nLen = 0;
	if (approxy4cST_t_count > 0) {
		approxy4cST = approxy4cST_t_s[0];
	}else{
		*pLen = 0;
		return -1;
	}
	nLen = (int)strlen(approxy4cST->gl_accessTokenSTR);
	if(nLen > 0){
		memcpy_s(szAccessTokenSTR,nLen,approxy4cST->gl_accessTokenSTR,nLen);
		*pLen = nLen;
		return 0;
	}else{
		return -1;
	}
}

int GetMyWebCtxPathSTR(char *szCtxPathSTR,int *pLen){
	Approxy4cST_t *approxy4cST = NULL;
	int nLen = 0;
	if (approxy4cST_t_count > 0) {
		approxy4cST = approxy4cST_t_s[0];
	}else{
		*pLen = 0;
		return -1;
	}
	nLen = (int)strlen(approxy4cST->gl_webCtxPathSTR);
	if(nLen > 0){
		memcpy_s(szCtxPathSTR,nLen,approxy4cST->gl_webCtxPathSTR,nLen);
		*pLen = nLen;
		return 0;
	}else{
		return -1;
	}
}


int GetNewAccessTokenByOldToken(char *szAccessTokenSTR,int *pLen,char *szOldToken){
	//验证Token是否失效
	return GetAccessTokenSTR(szAccessTokenSTR, pLen);
}



int GetClusterServer(Approxy4cST_t *approxy4cST){
	// int nRet = 0;
	int destnum = 0;
	char *revMsg[32] = {NULL};
	int arrayIndex = 0;
	if(approxy4cST->nServerSTArraySize == 0){
		char profileval[128] = {0};
        memcpy_s(profileval,strlen(clusterServerHostAndPort),clusterServerHostAndPort,strlen(clusterServerHostAndPort));
		split((char *)profileval,";",revMsg,&destnum);
		if(destnum > 0){
			int i = 0;
			ServerST_t *pServerST = NULL;
			for(;i<destnum;i++){
				int num = 0;
				char * msg[32] = {NULL};
				MallocBuf(ServerST_t,approxy4cST->pServerSTArray[i],sizeof(ServerST_t));
				split(revMsg[i],":",msg,&num);
				MallocMem(ServerST_t,pServerST);
				if(num > 1){
					memset(pServerST->serverIP,0,24);
					memcpy_s(pServerST->serverIP,strlen(msg[0]),msg[0],strlen(msg[0]));
					pServerST->serverPort = atoi(msg[1]);
					//memcpy_s(&pServerSTArray[arrayIndex],sizeof(ServerST_t),&pServerST,sizeof(ServerST_t));
					memset(approxy4cST->pServerSTArray[arrayIndex]->serverIP,0,24);
					memcpy_s(approxy4cST->pServerSTArray[arrayIndex]->serverIP,strlen(pServerST->serverIP),pServerST->serverIP,strlen(pServerST->serverIP));
					approxy4cST->pServerSTArray[arrayIndex]->serverPort = pServerST->serverPort;
					approxy4cST->nServerSTArraySize = ++arrayIndex;
				}else if(num == 1){
					memcpy_s(pServerST->serverIP,strlen(msg[0]),msg,strlen(msg[0]));
					pServerST->serverPort = RYN_DEFAULT_ROUTEPORT;
					//memcpy_s(&pServerSTArray[arrayIndex],sizeof(ServerST_t),&pServerST,sizeof(ServerST_t));
					memcpy_s(approxy4cST->pServerSTArray[arrayIndex]->serverIP,strlen(pServerST->serverIP),pServerST->serverIP,strlen(pServerST->serverIP));
					approxy4cST->pServerSTArray[arrayIndex]->serverPort = pServerST->serverPort;
					approxy4cST->nServerSTArraySize = ++arrayIndex;
                    fn_RYN_LOG_DEBUG(TAG,"GetClusterServer...");
				}
				FreeMem(pServerST);
			}
		}
	}
	return 0;
}